#pragma once
#include <iostream>
#include <sys/wait.h>
#include <functional>
#include "Socket.hpp"
#include "Log.hpp"
namespace tcpServerModule
{
    using namespace socketModule;
    using namespace LogModule;

    using tcphandler_t = std::function<bool (sockptr, InetAddr)>;
    // zdl:: 只负责进行 IO
    class tcpServer
    {
    public:
        tcpServer(int port): _listenSockp(std::make_unique<tcpSocket>()),
        _running(false), _port(port)
        {
        }
        ~tcpServer()
        {
            _listenSockp->close();
        }
        void inintServer(tcphandler_t handler)
        {
            _handler = handler;
            _listenSockp->bulidTcpSocketMethod(_port);

        }
        void loop()
        {
            _running = true;
            while (_running)
            {
                InetAddr clientaddr;
                // 1. accept 
                auto sockfd = _listenSockp->accepter(&clientaddr);
                if (sockfd == nullptr) return ;
                // 2. IO 处理
                LOG(LogLevel::DEBUG) << "get a new client, info is: " << clientaddr.Addr();
                // sockfd->Recv();
                // sockfd->Send()
                pid_t id = fork();
                if (id == 0)
                {
                    _listenSockp->close();
                    if (fork() > 0) exit(0);
                    _handler(sockfd, clientaddr);
                    exit(0);
                } 
                sockfd->close();
                ::waitpid(id, nullptr, 0);


            }
            
        }

    private:
        // 一定需要有一个 listensocket
        std::unique_ptr<Socket> _listenSockp;
        bool _running;
        tcphandler_t _handler;
        int _port;
    };
}